package com.project.web.config.filter;

import com.project.common.core.utils.JacksonUtil;
import com.project.common.core.utils.exception.Result;
import com.project.common.core.utils.redis.RedisClient;
import com.project.common.core.utils.redis.RedisConsts;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.io.IOException;

import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;

/**
 * JWT校验过滤器
 *
 * @author wyy
 * @date 2020-05-18
 */
@Component
public class JwtCheckGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {

    /**
     * 日志工具类
     */
    public static final Logger log = LoggerFactory.getLogger(JwtCheckGatewayFilterFactory.class);

    /**
     * 注入redis工具类
     */
    @Resource(name = "redisClient")
    private RedisClient redisClient;

    @Override
    public GatewayFilter apply(Object config) {
        return (exchange, chain) -> {
            // 获取请求
            ServerHttpRequest request = exchange.getRequest();
            String contextPath = request.getURI().getPath();

            // 校验请求路径/system/v2/api-docs
            if (contextPath.contains("common") || contextPath.contains("anon")||contextPath.contains("/v2/api-docs")) {
                return chain.filter(exchange);
            }

            // 忽略不校验的appId
            String apiId = request.getHeaders().getFirst("apiId");
            if (StringUtils.isNotBlank(apiId) && apiId.equals("358607697634592405")) {
                return chain.filter(exchange);
            }

            // 获取Response
            ServerHttpResponse response = exchange.getResponse();
            HttpHeaders httpHeaders = response.getHeaders();
            httpHeaders.add("Content-Type", "application/json; charset=UTF-8");
            httpHeaders.add("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");

            // 校验token是否正常
            String apiToken = request.getHeaders().getFirst("apiToken");
            Object redisApiToken = redisClient.get(RedisConsts.API_TOKEN_KEY + apiId);
            if (StringUtils.isBlank(apiToken) || StringUtils.isBlank(apiId)
                    || redisApiToken == null || !StringUtils.equals(redisApiToken.toString(), apiToken)) {

                //返回错误提示
                Result<String> result = new Result<>();
                result.setResult("success");
                result.setErrorCode("1007");
                result.setErrorMsg("缺少必须的参数");
                try {
                    String jsonStr = JacksonUtil.toJsonStr(result);
                    DataBuffer bodyDataBuffer = response.bufferFactory().wrap(jsonStr.getBytes());
                    return response.writeWith(Mono.just(bodyDataBuffer));
                } catch (IOException e) {
                    log.error("API 网关限速JSON转化出错");
                }

                return null;
            } else {
                // 如果apiToken 令牌验证通过，则重置生效时间
                redisClient.set(RedisConsts.API_TOKEN_KEY + apiId, apiToken, RedisConsts.API_TOKEN_EXPIRE);
                return chain.filter(exchange);
            }

        };
    }
}
